Use the surface output event to keep track of the suggested scale value
authorAndreas Pokorny <andreas.pokorny@canonical.com>
Tue, 19 Jul 2016 12:56:34 +0000 (14:56 +0200)
committerWilliam Hua <william.hua@canonical.com>
Wed, 10 Aug 2016 17:36:38 +0000 (13:36 -0400)
The event will be sent when the surface becomes visible on an output. With this change the GdkMirWindowImpl keeps track of the scale value and sends a configure event on change.

Signed-off-by: Andreas Pokorny <andreas.pokorny@canonical.com>
gdk/mir/gdkmir-private.h
gdk/mir/gdkmireventsource.c
gdk/mir/gdkmirwindowimpl.c

index 84051a7ed74c01360278ae72a80c55540e04c7de..53f5a6625108ea108f668ea062f4676a73286396 100644 (file)
@@ -89,6 +89,8 @@ void _gdk_mir_window_impl_set_surface_state (GdkMirWindowImpl *impl, MirSurfaceS
 
 void _gdk_mir_window_impl_set_surface_type (GdkMirWindowImpl *impl, MirSurfaceType type);
 
+void _gdk_mir_window_set_surface_output (GdkWindow *window, gdouble scale);
+
 void _gdk_mir_window_impl_set_cursor_state (GdkMirWindowImpl *impl, gdouble x, gdouble y, gboolean cursor_inside, guint button_state);
 
 void _gdk_mir_window_impl_get_cursor_state (GdkMirWindowImpl *impl, gdouble *x, gdouble *y, gboolean *cursor_inside, guint *button_state);
index 458228a246455e241792a0fdaaa9765e020ef9a1..b829c8f0acfd754871459654b6ca0ec326b1c869 100644 (file)
@@ -544,6 +544,13 @@ handle_close_event (GdkWindow *window)
   gdk_window_destroy_notify (window);
 }
 
+static void
+handle_surface_output_event (GdkWindow                  *window,
+                             const MirSurfaceOutputEvent *event)
+{
+  _gdk_mir_window_set_surface_output (window, mir_surface_output_event_get_scale (event));
+}
+
 typedef struct
 {
   GdkWindow *window;
@@ -598,6 +605,9 @@ gdk_mir_event_source_queue_event (GdkDisplay     *display,
     case mir_event_type_close_surface:
       handle_close_event (window);
       break;
+    case mir_event_type_surface_output:
+      handle_surface_output_event (window, mir_event_get_surface_output_event (event));
+      break;
     default:
       g_warning ("Ignoring unknown Mir event %d", mir_event_get_type (event));
       // FIXME?
index 1a19ec9b6121448d5b011113ef4a8a502567deb5..3d234cd3b1db5413966eeff1fc31fb3a58a6cd8a 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <inttypes.h>
+#include <math.h>
 
 #include "config.h"
 
@@ -65,6 +66,7 @@ struct _GdkMirWindowImpl
 
   /* Surface being rendered to (only exists when window visible) */
   MirSurface *surface;
+  MirBufferStream *buffer_stream;
 
   /* Cairo context for current frame */
   cairo_surface_t *cairo_surface;
@@ -80,6 +82,8 @@ struct _GdkMirWindowImpl
 
   /* TRUE if cursor is inside this window */
   gboolean cursor_inside;
+
+  gint output_scale;
 };
 
 struct _GdkMirWindowImplClass
@@ -91,6 +95,14 @@ G_DEFINE_TYPE (GdkMirWindowImpl, gdk_mir_window_impl, GDK_TYPE_WINDOW_IMPL)
 
 static cairo_surface_t *gdk_mir_window_impl_ref_cairo_surface (GdkWindow *window);
 
+static void
+drop_cairo_surface (GdkWindow *window)
+{
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
+
+  g_clear_pointer (&impl->cairo_surface, cairo_surface_destroy);
+}
+
 GdkWindowImpl *
 _gdk_mir_window_impl_new (void)
 {
@@ -144,6 +156,7 @@ gdk_mir_window_impl_init (GdkMirWindowImpl *impl)
 {
   impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
   impl->surface_state = mir_surface_state_unknown;
+  impl->output_scale = 1;
 }
 
 static void
@@ -356,6 +369,7 @@ ensure_surface_full (GdkWindow *window,
                                       impl->has_rect ? &impl->rect : NULL,
                                       impl->has_rect ? impl->edge : mir_edge_attachment_any,
                                       buffer_usage);
+  impl->buffer_stream = mir_surface_get_buffer_stream (impl->surface);
 
   /* FIXME: can't make an initial resize event */
   // MirEvent *resize_event;
@@ -448,6 +462,7 @@ gdk_mir_window_impl_ref_cairo_surface (GdkWindow *window)
   if (window->gl_paint_context)
     {
       cairo_surface = cairo_image_surface_create (pixel_format, window->width, window->height);
+      cairo_surface_set_device_scale (cairo_surface, (double) impl->output_scale, (double) impl->output_scale);
     }
   else if (impl->visible)
     {
@@ -496,6 +511,7 @@ gdk_mir_window_impl_ref_cairo_surface (GdkWindow *window)
                                                            region.width,
                                                            region.height,
                                                            region.stride);
+      cairo_surface_set_device_scale (cairo_surface, (double) impl->output_scale, (double) impl->output_scale);
     }
   else
     cairo_surface = cairo_image_surface_create (pixel_format, 0, 0);
@@ -1344,8 +1360,8 @@ static gint
 gdk_mir_window_impl_get_scale_factor (GdkWindow *window)
 {
   //g_printerr ("gdk_mir_window_impl_get_scale_factor window=%p\n", window);
-  /* Don't support monitor scaling */
-  return 1;
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
+  return impl->output_scale;
 }
 
 static void
@@ -1603,6 +1619,30 @@ gdk_mir_window_get_mir_surface (GdkWindow *window)
   return impl->surface;
 }
 
+void
+_gdk_mir_window_set_surface_output (GdkWindow *window, gdouble scale)
+{
+  // g_printerr ("_gdk_mir_window_impl_set_surface_output impl=%p\n", impl);
+  GdkMirWindowImpl *impl = GDK_MIR_WINDOW_IMPL (window->impl);
+  GdkRectangle area = {0, 0, window->width, window->height};
+  cairo_region_t *region;
+  gint new_scale = (gint) round (scale);
+
+  if (impl->output_scale != new_scale)
+    {
+      impl->output_scale = new_scale;
+
+      drop_cairo_surface (window);
+
+      if (impl->buffer_stream)
+        mir_buffer_stream_set_scale (impl->buffer_stream, (float) new_scale);
+
+      region = cairo_region_create_rectangle (&area);
+      _gdk_window_invalidate_for_expose (window, region);
+      cairo_region_destroy (region);
+    }
+}
+
 static void
 gdk_mir_window_impl_class_init (GdkMirWindowImplClass *klass)
 {